home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / mac / comm / revrdist.sit / RevRdist / RevRdist src / copyfile.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-07-30  |  10.3 KB  |  445 lines  |  [TEXT/KAHL]

  1. /*
  2.  * copyfile.c - routines to copy a file from server to client
  3.  */
  4. #include "RevRdist.h"
  5. #include "dispatch.h"
  6.  
  7. void updateDesktop (CInfoPBRec *);
  8.  
  9. static Longint lastflush = 0;
  10.  
  11.  
  12. /*
  13.  *=========================================================================
  14.  * copyFile (sp, cp, name) - copy file from server to client
  15.  * entry:    first param = pointer to catalog list node for server file
  16.  *            second param = pointer to catalog list node for client file
  17.  *                the information here is updated if the copy succeeds.
  18.  *            third param = name of client folder to get file
  19.  *=========================================================================
  20.  */
  21. DISPATCHED (copyFile)
  22. {
  23. #define    COPYBUFSZ        16384
  24.     struct    lm
  25.     {
  26.         frame_t            f;
  27.         cnode_t *        sp;            /* copy of first arg */
  28.         cnode_t *        cp;            /* copy of second arg */
  29.         StringPtr        name;        /* copy of third arg */
  30.         Ptr                bufp;        /* ptr to I/O buffer */
  31.         HParamBlockRec    src;        /* param block for reading */
  32.         HParamBlockRec    dst;        /* param block for writing */
  33.     };
  34.     typedef struct lm    lm_t;
  35.     register lm_t *        m;
  36.     Ptr                    bufp;        /* temp copy of lm.bufp */
  37.     OSErr                error;
  38.     Longint                l;            /* byte count */
  39.     short                result;        /* our return value */
  40.     Integer                temp;
  41.     CInfoPBRec            cb;            /* get/setCatInfo param block */
  42.     Str255                cbuf;        /* buffer for numeric conversions */
  43.  
  44.     m = *(lm_t **)fh;
  45.     result = request;
  46.     error = 0;
  47.     switch (request)
  48.     {
  49.     case R_INIT:
  50.         if (ClueID = resizeFrame (fh, sizeof (lm_t)))
  51.             return R_ERROR;
  52.         if ((bufp = NewPtr (COPYBUFSZ)) == nil)
  53.         {
  54.             if ((ClueID = MemError()) == 0)
  55.                 ClueID = memFullErr;
  56.             return R_ERROR;
  57.         }
  58.         m = *(lm_t **)fh;
  59.         m->sp = (cnode_t *)argv[0];
  60.         m->cp = (cnode_t *)argv[1];
  61.         m->name = (StringPtr)argv[2];
  62.         m->bufp = bufp;
  63.         m->f.state = 1;
  64.         return R_CONT;
  65.         
  66.     case R_CONT:
  67.         /*
  68.          * Handle only the first step of R_CONT here, and the rest after
  69.          * the request switch.
  70.          */
  71.         if (m->f.state == 1)
  72.         {
  73.             l = m->sp->in.f.fileLen + m->sp->in.f.rsrcLen;
  74.             NumToString (l, cbuf);
  75.             notice (L_COPYING, cbuf, m->sp->name, m->name, nil);
  76.             m->f.state = 2;
  77.             return R_CONT;
  78.         }
  79.         break;
  80.     
  81.     case R_BACKOUT:
  82.     case R_QUIT:
  83.         goto cleanexit;
  84.     }
  85.  
  86.     /*
  87.      * The body of the R_CONT code:
  88.      */
  89.     if (Flags & DB_LISTONLY)
  90.         goto cleanexit;
  91.     /*
  92.      * Honor quit only if we are not the startup application, so that
  93.      * we don't leave files missing if an antsy student cancels
  94.      * an automatic RevRdist.
  95.      */
  96.     if (Quit && !(Flags & DB_STARTUP))
  97.         goto cleanexit;
  98.     switch (m->f.state)
  99.     {
  100.     case 2:        
  101.         /*
  102.          * open the source file on the server.
  103.          * if that succeeds, purge and create the client destination file.
  104.          */
  105.         m->src.fileParam.ioNamePtr = m->sp->name;
  106.         m->src.fileParam.ioVRefNum = ServerVol;
  107.         m->src.ioParam.ioPermssn = fsRdPerm;
  108.         m->src.fileParam.ioDirID = m->sp->parID;
  109.         error = PBHOpen (&m->src, false);
  110.         if (error)
  111.         {
  112.             if (error == fnfErr)
  113.             {
  114.                 notice (L_MISSING, m->sp->name, nil);
  115.                 goto cleanexit;
  116.             }
  117.             Clue1 = (SP) "\pPBHOpen";
  118.             goto syserrexit;
  119.         }
  120.         if (m->cp->dirID)
  121.         {
  122.             /*
  123.              * If the file already exists, delete it
  124.              */
  125.             error = discard (m->cp, false);
  126.             if (error)
  127.             {
  128.                 ClueID = error;
  129.                 if (error == fBsyErr)
  130.                     notice (E_FILE, m->cp->name, nil);
  131.                 else
  132.                     warning (E_FILE, m->cp->name, nil);
  133.                 goto cleanexit;
  134.             }
  135.         }
  136.         m->dst.fileParam.ioNamePtr = m->cp->name;
  137.         m->dst.fileParam.ioVRefNum = ClientVol;
  138.         m->dst.fileParam.ioDirID = m->cp->parID;
  139.         error = PBHCreate (&m->dst, false);
  140.         if (error)
  141.         {
  142.             Clue1 = (SP) "\pPBHCreate";
  143.             goto syserrexit;
  144.         }
  145.         /*
  146.          * If the file has a data fork, set up to copy it.
  147.          */
  148.         if (m->sp->in.f.fileLen)
  149.         {
  150.             m->dst.ioParam.ioPermssn = fsRdWrPerm;
  151.             error = PBHOpen (&m->dst, false);
  152.             if (error)
  153.             {
  154.                 Clue1 = (SP) "\pPBHOpen";
  155.                 goto syserrexit;
  156.             }
  157.             m->f.state = 3;
  158.         }
  159.         else
  160.         {
  161.             (void) PBClose ((ParmBlkPtr)&m->src, false);
  162.             m->f.state = 4;
  163.         }
  164.         break;
  165.  
  166.     case 3:
  167.     case 5:
  168.         /*
  169.          * copy one fork in COPYBUFSZ chunks
  170.          */
  171.         m->src.ioParam.ioBuffer = m->bufp;
  172.         m->src.ioParam.ioReqCount = COPYBUFSZ;
  173.         m->src.ioParam.ioActCount = 0;
  174.         m->src.ioParam.ioPosMode = fsAtMark;
  175.         error = PBRead ((ParmBlkPtr)&m->src, false);
  176.         if ((l = m->src.ioParam.ioActCount) != 0)
  177.         {
  178.             m->dst.ioParam.ioBuffer = m->bufp;
  179.             do
  180.             {
  181.                 m->dst.ioParam.ioReqCount = l;
  182.                 m->dst.ioParam.ioActCount = 0;
  183.                 m->dst.ioParam.ioPosMode = fsAtMark;
  184.                 error = PBWrite ((ParmBlkPtr)&m->dst, false);
  185.                 if (error)
  186.                     break;
  187.                 l -= m->dst.ioParam.ioActCount;
  188.                 m->dst.ioParam.ioBuffer += m->dst.ioParam.ioActCount;
  189.             } while (l > 0);
  190.             if (error)
  191.             {
  192.                 Clue1 = (SP) "\pPBWrite";
  193.                 goto syserrexit;
  194.             }
  195.         }
  196.         else if (error && error != eofErr)
  197.         {
  198.             Clue1 = (SP) "\pPBRead";
  199.             goto syserrexit;
  200.         }
  201.         else if (error == eofErr)
  202.         {
  203.             /*
  204.              * one fork copy complete.
  205.              */
  206.             (void) PBClose ((ParmBlkPtr)&m->src, false);
  207.             m->src.ioParam.ioRefNum = 0;
  208.             error = PBClose ((ParmBlkPtr)&m->dst, false);
  209.             m->dst.ioParam.ioRefNum = 0;
  210.             if (error)
  211.             {
  212.                 Clue1 = (SP) "\pPBClose";
  213.                 goto syserrexit;
  214.             }
  215.             m->f.state++;
  216.         }
  217.         break;
  218.  
  219.     case 4:
  220.         /*
  221.          * set up to copy resource fork
  222.          * open source and destination forks
  223.          */
  224.         if (m->sp->in.f.rsrcLen == 0)
  225.         {
  226.             m->f.state = 6;
  227.             break;
  228.         }
  229.         ZERO (m->src);
  230.         m->src.fileParam.ioNamePtr = m->sp->name;
  231.         m->src.fileParam.ioVRefNum = ServerVol;
  232.         m->src.ioParam.ioPermssn = fsRdPerm;
  233.         m->src.fileParam.ioDirID = m->sp->parID;
  234.         error = PBHOpenRF (&m->src, false);
  235.         if (error)
  236.         {
  237.             Clue1 = (SP) "\pPBHOpenRF";
  238.             goto syserrexit;
  239.         }
  240.         ZERO (m->dst);
  241.         m->dst.fileParam.ioNamePtr = m->cp->name;
  242.         m->dst.fileParam.ioVRefNum = ClientVol;
  243.         m->dst.ioParam.ioPermssn = fsRdWrPerm;
  244.         m->dst.fileParam.ioDirID = m->cp->parID;
  245.         error = PBHOpenRF (&m->dst, false);
  246.         if (error)
  247.         {
  248.             Clue1 = (SP) "\pPBHOpenRF";
  249.             goto syserrexit;
  250.         }
  251.         m->f.state++;
  252.         break;
  253.  
  254.     case 6:
  255.         /*
  256.          * Both forks copied, copy Finder information
  257.          */
  258.         ZERO (cb);
  259.         cb.hFileInfo.ioNamePtr = m->cp->name;
  260.         cb.hFileInfo.ioVRefNum = ClientVol;
  261.         cb.hFileInfo.ioDirID = m->cp->parID;
  262.         error = PBGetCatInfo (&cb, false);
  263.         if (error)
  264.         {
  265.             Clue1 = (SP) "\pPBGetCatInfo";
  266.             goto syserrexit;
  267.         }
  268.         cb.hFileInfo.ioDirID = m->cp->parID;
  269.         temp = cb.hFileInfo.ioFlFndrInfo.fdFldr;
  270.         cb.hFileInfo.ioFlFndrInfo = m->sp->in.f.finfo;
  271.         cb.hFileInfo.ioFlFndrInfo.fdFlags &= ~0x0010;    /* clear inited bit */
  272.         cb.hFileInfo.ioFlFndrInfo.fdFldr = temp;
  273.         cb.hFileInfo.ioFlCrDat = m->sp->crDate;
  274.         cb.hFileInfo.ioFlMdDat = m->sp->mdDate;
  275.         error = PBSetCatInfo (&cb, false);
  276.         if (error)
  277.         {
  278.             Clue1 = (SP) "\pPBSetCatInfo";
  279.             goto syserrexit;
  280.         }
  281.         /*
  282.          * If the file did not previously exist and it is an application,
  283.          * update the Desktop file to know about it.
  284.          */
  285.         if (m->cp->dirID == 0
  286.         &&     cb.hFileInfo.ioFlFndrInfo.fdType == 'APPL'
  287.         &&  (cb.hFileInfo.ioFlFndrInfo.fdFlags & fHasBundle)
  288.         )
  289.             updateDesktop (&cb);
  290.         saveCatInfo (&cb, m->cp);
  291.         /*
  292.          * Doing a Flush after every file slowed things down too much
  293.          * on lots of small files, so we flush only every so often
  294.          */
  295.         l = TickCount ();
  296.         if (l - lastflush > 60 * 20)
  297.         {
  298.             m->dst.fileParam.ioNamePtr = nil;
  299.             error = PBFlushVol ((ParmBlkPtr)&m->dst, false);
  300.             if (error)
  301.             {
  302.                 Clue1 = (SP) "\pPBFlushVol";
  303.                 goto syserrexit;
  304.             }
  305.             lastflush = l;
  306.         }
  307.         goto cleanexit;
  308.     }
  309.     return result;
  310.  
  311. syserrexit:
  312.     ClueID = error;
  313.     Clue2 = nil;
  314.     warning (E_SYS, (SP) "\pcopyFile", nil);
  315. cleanexit:
  316.     if (GetHandleSize ((Handle)fh) >= sizeof (lm_t))
  317.     {
  318.         if (m->dst.ioParam.ioRefNum)
  319.             (void) PBClose ((ParmBlkPtr)&m->dst, false);
  320.         if (m->src.ioParam.ioRefNum)
  321.             (void) PBClose ((ParmBlkPtr)&m->src, false);
  322.         if (error && m->f.state > 2)
  323.         {
  324.             ZERO (m->dst);
  325.             m->dst.fileParam.ioNamePtr = m->cp->name;
  326.             m->dst.fileParam.ioVRefNum = ClientVol;
  327.             m->dst.fileParam.ioDirID = m->cp->parID;
  328.             (void) PBHDelete (&m->dst, false);
  329.         }
  330.         if (m->bufp)
  331.             DisposPtr (m->bufp);
  332.     }
  333.     if (! error)
  334.         statMsgClr ();
  335.     return (popCall (result, nil));
  336. }
  337.  
  338.  
  339.  
  340. /*
  341.  *=========================================================================
  342.  * updateDesktop (cip) - update Finder Desktop file to know about new
  343.  *    application.
  344.  * entry:    cip = pointer to CInfoPBRec describing file
  345.  * exit:    Desktop updated (if possible)
  346.  *            errors are silently ignored
  347.  *=========================================================================
  348.  */
  349. void
  350. updateDesktop (cip)
  351.     CInfoPBRec *cip;
  352. {
  353. struct    applinfo
  354. {
  355.     OSType                creator;        /* creator/owner id */
  356.     Longint                dirID;            /* directory containing appl */
  357. /*    char                applname[];     /* file name */
  358. };
  359. typedef    struct applinfo    api_t;
  360.  
  361. register OSType            creator;        /* application signature */
  362. register api_t *        fp;                /* pointer to ap info header */
  363. register Size            len;            /* temp byte length */
  364. register Size            origlen;        /* original resource size */
  365. register Ptr            p, ep;
  366. static    Handle            hdl = 0;        /* handle to APPL resource */
  367.  
  368.     if (hdl == 0)
  369.     {
  370.         /*
  371.          * First call, get APPL resource
  372.          */
  373.         hdl = GetResource ('APPL', 0);    /* see if available already */
  374.         if (hdl == 0)
  375.         {
  376.             /*
  377.              * Try to open Finder's Desktop file to find resource
  378.              */
  379.             Deskrefnum = OpenRFPerm((SP)"\pDesktop", ClientVol, fsRdWrPerm);
  380.             if (Deskrefnum != -1)
  381.                 hdl = GetResource ('APPL', 0);
  382.         }
  383.         if (hdl == 0)
  384.         {
  385.             if (Deskrefnum != -1)
  386.             {
  387.                 CloseResFile (Deskrefnum);
  388.                 Deskrefnum = -1;
  389.             }
  390.             hdl = (Handle) -1;
  391.             return;
  392.         }
  393.     }
  394.     else if (hdl == (Handle) -1)
  395.         return;
  396.     LoadResource (hdl);
  397.     if (ResError())
  398.         return;
  399.     /*
  400.      * Now, search the resource for an entry with a matching creator
  401.      */
  402.     creator = cip->hFileInfo.ioFlFndrInfo.fdCreator;
  403.     origlen = SizeResource (hdl);
  404.     for (p = *hdl, ep = p + origlen; p < ep; p += len)
  405.     {
  406.         fp = (api_t *)p;
  407.         p = (Ptr) (fp+1);            /* advance over header */
  408.         len = (*p | 1) + 1;            /* chars in name (rounded) */
  409.         if (fp->creator == creator)
  410.         {
  411.             /*
  412.              * Found it.  If the containing directory has changed, update
  413.              * the resource.
  414.              */
  415.             if (fp->dirID != cip->hFileInfo.ioFlParID)
  416.             {
  417.                 fp->dirID = cip->hFileInfo.ioFlParID;
  418.                 ChangedResource (hdl);
  419.                 WriteResource (hdl);
  420.             }
  421.             return;
  422.         }
  423.     }
  424.     /*
  425.      * No matching signature in current APPL list.
  426.      * Add one.
  427.      */
  428.     len = sizeof (api_t);
  429.     p = (Ptr) cip->hFileInfo.ioNamePtr;
  430.     len += (*p | 1) + 1;
  431.     HUnlock (hdl);
  432.     SetHandleSize (hdl, len + origlen);
  433.     if (MemError())
  434.         return;
  435.     ep = *hdl + origlen;
  436.     fp = (api_t *)ep;
  437.     fp->creator = cip->hFileInfo.ioFlFndrInfo.fdCreator;
  438.     fp->dirID = cip->hFileInfo.ioFlParID;
  439.     ep = (Ptr) (fp+1);
  440.     COPYPS (p, ep);
  441.     if ((*ep & 1) == 0)
  442.         ep[*ep + 1] = 0;
  443.     ChangedResource (hdl);
  444.     WriteResource (hdl);
  445. }